<?php
class Form_Editor extends Form_Base
{
    protected $_type;
    protected $_data;
    protected $_group_level;
    protected $_group_count;
    protected $_app_controller;

    public function __construct ($type, $controller)
    {
        $this->_type = $type;
        $this->_data = array();
        $this->_group_level = 0;
        $this->_group_count = array();
        $this->_app_controller = $controller;
    }

    public function set_data ($data)
    {
        $this->_data = $data;
        $this->_group_level = 0;
        $this->_group_count = array();
        return $this;
    }

    private function formItemsConfig ($type)
    {
        $query = $this->_app_controller->getFormItemsConfig($type);

        if (! empty($query))
            return $query;

        return $this->getFormItemsConfig($type);
    }

    public function build_form ($show_type = 'form', $type = NULL, $group_suffix = NULL, $form_data = NULL)
    {
        $type = empty($type) ? $this->_type : $type;

        $query = $this->formItemsConfig($type);
        $ul = "<ul class=\"$show_type\">\n";
        foreach ($query as $rs)
        {
            // set value for edit
            if (NULL === $form_data)
            {
                if (! empty($this->_data))
                    $rs['value'] = Arr::get($this->_data, $rs['input_name']);
            }
            else
                $rs['value'] = Arr::get($form_data, $rs['input_name']);

            if ($show_type == 'group')
                $rs['input_name'] = $rs['input_name'].$group_suffix;
            $input_element = $this->build_input_element($rs, $group_suffix);
$ul .=<<<EOF
<li class="{$rs['class']}">
    <label>{$rs['label']}</label>
    <span>
        $input_element
    </span>
</li>

EOF;
            
        }

        $ul .= "</ul>\n";

        if ($show_type == 'group')
        {
            $ul =<<<EOF
<div class="grouplist">
    <p class="action"><span onclick="form_group_action('add', this)">添加</span>, <span onclick="form_group_action('remove', this)">删除</span></p>
    $ul
</div>

EOF;
        }
        else if ($show_type == 'form')
        {
            if (empty($this->_data))
                $button = '';
            else
                $button = $this->build_buttons ('list');

            $ul =<<<EOF
<script>

function form_group_action(action, item)
{
    if (action == 'remove')
    {
        len = $(item).parent().parent().parent().children().length;
        if (len <= 1)
        {
            alert('最后一个元素不允许删除');
            return false;
        }

        $(item).parent().parent().remove();
        $('.grouplist').each (function (grpbox) {
                form_group_rebuild_name_index($(grpbox));
            });
        form_group_rebuild_name_index (newbx)
        return false;
    }
    else
    {
        boxes = $(item).parent().parent();
        newbx = $(boxes[0]).clone();
        $(boxes[0]).parent().append(newbx);
        form_group_rebuild_name_index (newbx)
        return false;
    }
}

function form_group_rebuild_name_index (item) 
{
    // 判断一级还是二级
    is_level1 = item.find('.grouplist').length;

    // 二级不用修正name
    if (! is_level1)
        return;

    level_index = item.index();

    suffix = '['+level_index+']';
    inputs = item.find(':input');
    for (var i = 0; i < inputs.length; ++i)
    {
        name = $(inputs[i]).attr('name');
        if (/\[\d+\]/.test(name))
        {
            $(inputs[i]).attr('name', name.replace(/\[\d+\]/, suffix));
        }
    }
}

function form_select_onchange (item)
{
    url   = $(item).attr('url');
    child = $(item).attr('child');
    value = $(item).attr('value');

    $.post(url, {'value':value}, function (o) {
        if (o.status == 0)
        {
            sel = $('select[name='+child+']').get(0);
            $(sel).html(o.html)
        }
    }, 'json');
}

</script>
<div class="formbox">
    <div class="btns">$button</div>
    <form action="" method="POST" onSubmit="return form_submit_it(this)">
        $ul
        <div class="actions"><input type="submit" name="submit_op" value="提交"></div>
    </form>
</div>
EOF;
        }

        return $ul;
    }


    private function build_input_element ($rs, $group_suffix)
    {
        switch ($rs['input_type'])
        {
        case 'text':
        case 'password':
        case 'hidden':
            $options = $rs['options'];
            if ($options == 'NULL')
                $options = '';

            if ($rs['input_type'] == 'text' && $options == 'readonly')
                return $rs['value'];
            else
            {
                $inputValue = htmlentities($rs['value'], ENT_COMPAT, 'UTF-8');
                $regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";

                return "<input type=\"{$rs['input_type']}\" name=\"{$rs['input_name']}\" tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\" value=\"$inputValue\" $options $regexExpress>";
            }
            break;


        case 'textarea':
            $regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";
            return "<textarea name=\"{$rs['input_name']}\" tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\" $regexExpress>{$rs['value']}</textarea>";
            break;

        case 'readonly':
            return $rs['value'];
            break;

        case 'editor': 
            $tmpValue = $rs['value'];
            $tmpTip = $rs['tip'];
            $tmpName  = $rs['input_name'];
            return <<<EOF
<script id="editorContainer$tmpTip" name="$tmpName" type="text/plain">
$tmpValue
</script>
<script type="text/javascript">
    var ue = UE.getEditor('editorContainer$tmpTip');
</script>

EOF;

        case 'select':
            $input = $this->build_select ($rs);
            return $input;
            break;

        case 'date' :
            $regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";
            return "<input type=\"text\" onclick=\"laydate()\" name=\"{$rs['input_name']}\" tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\" $regexExpress value=\"{$rs['value']}\" class=\"date\">";
            break;
        case 'map' :
        	$regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";
        	return <<<EOF
        	<input type="text" name="{$rs['input_name']}" tip="{$rs['tip']}" errormsg="{$rs['errormsg']}" {$regexExpress} value="{$rs['value']}">            
            <div id="map-container" style="width:100%;height:300px"></div>                   	
EOF;
        	
        	break;
        
        case 'multi-date':
        	$regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";
        	return <<<EOF
            <div id='multiD'></div>
            
            <h3>产品库存量和价格设定</h3>
            <button type='button' onclick='showsetbox()'>刷新</button>
        	<div id='setD'></div>
        	
        	<div id='setpriceperson' style='display:none;padding:10px;'>
        	<span>价格</span>
        	<input type='text' name='setprice' style='width:180px;'/>
        	<span>库存量</span>
        	<input type='text' name='setperson'style='width:180px;margin-bottom:20px;'/>
        	<input type='hidden' name='ppdate' disabled="disabled"/>
        	<button type='button' onclick='sub_price_person_data()'>确定</button>
        	<button type='button' onclick='layer.close(global_layer_index)'>取消</button>
        	</div>
        	
        	<div id='confirm-person-price-edit' style="width: 100px;
        	 line-height: 20px;
             margin: 20px 0;
             text-align: center;
             cursor: pointer;
             background-color: #4dc957;
             color: #fff;
             border-radius: 2px;
             border: none;">确认修改</div>
        	
        	<input type="hidden" name="{$rs['input_name']}" tip="{$rs['tip']}" errormsg="{$rs['errormsg']}" $regexExpress value="{$rs['value']}">

        	<style type="text/css" media="screen">
        	.kalendae .k-calendar { width: 290px; }
        	.kalendae .k-title, .kalendae .k-header, .kalendae .k-days { width: 290px; }
                .kalendae .k-days span { background: #ddd; width: 34px; height: 34px; line-height: 34px; text-align: center; padding: 0; margin: 2px; }
                .kalendae .k-header span {  width: 36px; height: 36px; line-height: 36px; text-align: center; }
                .kalendae .k-caption {  font-weight: bold; font-size: 18px;   color: #262626;}
                #multiD {  width: 290px; position: relative;}
                #setD {  width: 290px; position: relative;}
                .kalendae .k-days span.k-in-month.k-active { background: #fff; color: #444; }
                .kalendae .k-days span.k-in-month { color: #fff; }
                .kalendae .k-days span.k-selected.k-active {  background: #2cda98; color: #fff; }
                .kalendae .k-days span.k-out-of-month {color:#fff;}
                .kalendae .k-days span.k-out-of-month.k-selected.k-active {color:#fff;background-color:#ddd;border:none;cursor:default;}
        	
        	</style>
            <script type="text/javascript">
        	    var global_kal=null;
        	    var global_kal2=null;
        	    var global_layer_index=null;
        	    //获取之前每个成团日期的价格
                var priceDetail=$('input[name=priceDetail]').val();           
                var priceDays=new Array();
                if(priceDetail){
                  priceDetail=priceDetail.split(',');
                  for( i in priceDetail){
                  var pday=priceDetail[i].split(':');
                  priceDays[pday[0]]=pday[1];
                 }
                }
        		//获取之前每个成团日期下的人数
                var personDetail=$('input[name=personDetail]').val();
                var personDays=new Array();
                if(personDetail){
                  personDetail=personDetail.split(',');
               
                  for( i in personDetail){
                  if(personDetail[i]){              
                    var perday=personDetail[i].split(':');
                    $.trim(perday[0]);
                    $.trim(perday[1]);
                    personDays[perday[0]]=perday[1];
                  }
                  }                
                }
        		//选定成团日期
        	    global_kal = new Kalendae({
                attachTo: document.getElementById("multiD"),
		        months:1,
                weekStart: 1,
	            mode:'multiple',
                useYearNav: true,
                useMonthNav: true,
                columnHeaderFormat: "dd",
                titleFormat: "YYYY年MM月",
               });
               //选定成团日期下的人数和价格
               global_kal2 = new Kalendae({
               attachTo: document.getElementById("setD"),
	           months:1,
               weekStart: 1,
	           mode:'multiple',
               useYearNav: true,
               useMonthNav: true,
               columnHeaderFormat: "dd",
               titleFormat: "YYYY年MM月",
               subscribe : {
                'date-clicked' : function (date) {
                              var d=date.format("YYYY-MM-DD");
        			          //存储现在编辑的日期
                              $("input[name='ppdate']").val(d);
        			          //判定之前是否已经设定了该成团日期的价格和人数
        			          //如果没有则默认为之前priceTotal和serviceMaxPersons的选项值
                              if(priceDays[d]){
                                $("input[name='setprice']").val(priceDays[d]);       
                              }else{ $("input[name='setprice']").val($("input[name='priceTotal']").val());}
                              if(personDays[d]){
                                $("input[name='setperson']").val(personDays[d]);
                              }else{ $("input[name='setperson']").val($("input[name='serviceMaxPersons']").val());}
        			          //打开编辑框
                              global_layer_index = layer.open({
                                type : 1,
                                closeBtn:0,
                                title : false,
                                area: ['200px', '200px'],
                                content : $('#setpriceperson')
                              });
                             return false;
                 }
                }
               });
               //初始化之前选定的日期
               var frees=$('input[name=freetimeDays]').val();
                if(frees){
                  frees=frees.split(",");
                  for(var i=0;i<frees.length;i++){
                  global_kal.addSelected(frees[i]);
                  global_kal2.addSelected(frees[i]);
                  }
                  global_kal.draw();
                  global_kal2.draw();
                }
               //关闭编辑框并储存数据
               function sub_price_person_data() {
                  var ppdate=$("input[name='ppdate']").val();
                  priceDays[ppdate]=$("input[name='setprice']").val();
                  personDays[ppdate]=$("input[name='setperson']").val();
                  layer.close(global_layer_index);
               }
        	   //刷新编辑日历，以便设定成团日期下的人数和价格
               function showsetbox() {
                  var data=global_kal.getSelected();
                  if(data){
                    data=data.split(",");
                    global_kal2.setSelected(data);
                    global_kal2.draw();
                  }        
               }
        	   //储存freetimeDays,priceDetail,personDetail
        	   $("#confirm-person-price-edit").click(function(){
                    //获取成团日期
                    var days = global_kal.getSelected();
                    $("input[name='freetimeDays']").val(days);
                    //获取每个成团日期的价格
                    var pricebasic=$("input[name='priceTotal']").val();
                    var priceofdays='';
                    if(days){
                      var pdaysarr=days.split(",");
                      for( i in pdaysarr){
                         var day=$.trim(pdaysarr[i]);
                         if(priceDays[day])
                         {priceofdays+=day+":"+priceDays[day]+",";}
                         else{priceofdays+=day+":"+pricebasic+",";}
                      } 
                      $("input[name='priceDetail']").val(priceofdays);
                    }
                    //获取每个成团日期的人数
                    var personbasic=$("input[name='serviceMinPersons']").val();
                    var personofdays='';
                    if(days){
                      var perdaysarr=days.split(",");
                      for( i in perdaysarr){
                         var day=$.trim(perdaysarr[i]);
                         if(personDays[day])
                         {personofdays+=day+":"+personDays[day]+",";}
                         else{personofdays+=day+":"+personbasic+",";}
                    } 
                    $("input[name='personDetail']").val(personofdays);
        			confirm("成团日期、成团人数和价格的修改已保存");
                   }
               });
       </script>
EOF;
        	break;        

        case 'radio':
            $options = $this->build_input_radio ($rs);
            return $options;
            break;
        
        case 'checkbox':
            $options = $this->build_input_checkbox ($rs);
            return $options;
            break;

        case 'group':
            $str = '';
            $index = 0;
            $this->_group_level += 1;
            $grp_type_name = $rs['param'];
            if (empty($this->_data) && empty($rs['value']))
                $rs['value'] = array(-1);
            
            foreach ($rs['value'] as $val)
            {
                $this->record_group_current_count();
                $suffix = $this->current_group_suffix();

                $str .= self::build_form('group', $grp_type_name, $suffix, $val);
                $index++;
            }
            $this->_group_level -= 1;
            return $str;
            break;

        case 'images':
        case 'file' :
            $element = Form_Element_Images::current()->build_form($rs);
            return $element;

        default:
            return '';
            break;
        }
    }

    private function build_input_radio ($item)
    {
        $inputs = array();

        $optstr = $item['options'];
        $optval = $item['value'];
        $opts = explode("\n", $optstr);
        $options = array();
        foreach ($opts as $rs)
        {
            if (empty($rs))
                continue;

            $items = explode('|', $rs);
            if (count($items) == 2 && ! empty($items[1]))
            {
                $value = $items[0];
                $label = $items[1];

                $options[] = array('label' => $label, 'value' => $value);
            }
        }


        foreach ($options as $opt)
        {
            $checked  = $optval !== NULL && $optval == $opt['value'] ?  'checked="checked"' : '';
            $inputs[] = "<input type=\"radio\" name=\"{$item['input_name']}\" tip=\"{$item['tip']}\" errormsg=\"{$item['errormsg']}\" value=\"{$opt['value']}\" $checked><i>{$opt['label']}</i>";
        }

        return implode("\n", $inputs);
    }

    private function build_select ($rs)
    {
        $optstr = Arr::get($rs, 'options');
        $value  = Arr::get($rs, 'value');
        $param  = Arr::get($rs, 'param');
        $tip    = Arr::get($rs, 'tip');

        if (preg_match('/^\s*function:(.+)$/', $optstr, $m))
        {
            $func = $m[1];
            $options = self::build_select_options_dynamic($func, $value, $param);
            $select = "<select name=\"{$rs['input_name']}\" tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\">$options</select>";
            $jsfunc  = "";
            $child   = '';
            $url     = '';

            if (! empty($param))
            {
                if (preg_match('/^attr:(.+)$/', $param, $m))
                {
                    $jsfunc = $m[1];
                    $child  = '';
                    $url    = '';
                }
                else if (preg_match('/^(\w+):(.+)$/', $param, $m))
                {
                    $jsfunc  = "onchange=\"form_select_onchange(this)\"";
                    $child = $m[1];
                    $url   = $m[2];
                }
            }
           
            $regexExpress = empty($rs['regex']) ? '' : "regex=\"{$rs['regex']}\"";

            $select = "<select name=\"{$rs['input_name']}\" $regexExpress tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\" $jsfunc child=\"$child\" url=\"$url\" val=\"$value\" >$options</select>";
 
        }
        else
        {
            $options = $this->build_select_options_static ($optstr, $value, $param);
            $child   = '';
            $url     = '';
            if (! empty($param))
            {
                if (preg_match('/^attr:(.+)$/', $param, $m))
                {
                    $jsfunc = $m[1];
                    $child  = '';
                    $url    = '';
                }
                else if (preg_match('/^(\w+):(.+)$/', $param, $m))
                {
                    $jsfunc  = "onchange=\"form_select_onchange(this)\"";
                    $child = $m[1];
                    $url   = $m[2];
                }
            }
            else
            {
                $jsfunc  = "";
            }

            $select = "<select name=\"{$rs['input_name']}\" tip=\"{$rs['tip']}\" errormsg=\"{$rs['errormsg']}\" $jsfunc child=\"$child\" url=\"$url\" val=\"$value\">$options</select>";
        }
    
        $select .= "&nbsp;&nbsp;<span>$tip</span>";

        return $select;
    }

    private function build_select_options_static ($optstr, $optval, $param)
    {
        $opts = explode("\n", $optstr);
        $options = array();
        foreach ($opts as $rs)
        {
            if (empty($rs))
                continue;

            $items = explode('|', $rs);
            if (count($items) == 2 && ! empty($items[1]))
            {
                $value = $items[0];
                $label = $items[1];

                $selected = $optval !== NULL && $optval == $value ? 
                            'selected="selected"' : '';
                $options[] = "<option value=\"$value\" $selected>$label</option>";
            }
            if (count($items)==1)
            {   
            	$value = $items[0];
            	$label = $items[0];
                $selected = $optval !== NULL && $optval == $value ? 
                            'selected="selected"' : '';
                $options[] = "<option value=\"$value\" $selected>$label</option>";
            }
        }

        return implode("\n", $options);
    }

    private function build_select_options_dynamic($func, $optval, $param)
    {
        $ret = array();
        if (! empty($param) && ! preg_match('/^(\w+):(.+)$/', $param))
        {
            $select_input_name = $param;
            $value = Arr::get($this->_data, $select_input_name);
            $ret = call_user_func($func, $value);
        }
        else
        {
            $ret = call_user_func($func);
        }

        $options = array();
        foreach ($ret as $id => $name)
        {
            $selected  = $optval !== NULL && $optval == $id ? 
                         'selected="selected"' : '';
                        
            $options[] = "<option value=\"$id\" $selected>$name</option>";
        }

        return implode("\n", $options);
    }

    private function build_input_checkbox($rs)
    {
        $optstr = Arr::get($rs, 'options');
        $value  = Arr::get($rs, 'value');
        $param  = Arr::get($rs, 'param');

        if (preg_match('/^\s*function:(.+)$/', $optstr, $m))
        {
           $func = $m[1];
           $checkbox = self::build_checkbox_dynamic($func, $value, $param,$rs['input_name']);   
        }
        else
        {
        $checkbox = $this->build_checkbox_static ($optstr, $value, $param,$rs['input_name']);
        }

        return $checkbox; 
    }

    private function build_checkbox_dynamic($func, $optval, $param,$input_name)
    {
        $ret = array();
        if (! empty($param) && ! preg_match('/^(\w+):(.+)$/', $param))
        {
           $value = Arr::get($this->_data, $param);
           $ret = call_user_func($func, $value);
        }
        else
        {
           $ret = call_user_func($func);
        }

        $options = array();
        foreach ($ret as $id => $name)
        {
           if(is_array($optval))
           {
             $checked='';
             foreach($optval as $val)
             {
                if($val!==null && $val == $id)
                {
                  $checked='checked="checked"';
                  break;
                }
             }
           }
           else
           {
             $checked  = $optval !== NULL && $optval == $id ?
             'checked="checked"' : '';
           }
           
           $options[] = "<input type='checkbox' name='".$input_name."[]' value=".$id." ".$checked."><i>".$name."</i>";
        }
                                                                                                                                                                                    
        return implode("\n", $options);
    }
    
    private function build_checkbox_static($optstr, $optval, $param,$input_name)
    {
        $opts = explode("\n", $optstr);
        $options = array();
        
        foreach ($opts as $rs)
        {
           if (empty($rs))
           continue;

           $items = explode('|', $rs);
           if (count($items) == 2 && ! empty($items[1]))
           {
              $value = $items[0];
              $label = $items[1];

              if(is_array($optval))
             {
                $checked='';
                foreach($optval as $val)
               {
                   if($val!==null && $val == $value)
                  {
                     $checked='checked="checked"';
                     break;
                  }
               }
             }
              else
             {
                $checked  = $optval !== NULL && $optval == $value ?
                'checked="checked"' : '';
             }

              $options[] = "<input type='checkbox' name='{$input_name}[]' value='{$value}' {$checked}><i>{$label}</i>";

           }
           
           if (count($items)==1)
           {
              $value = $items[0];
              $label = $items[0];
               
              if(is_array($optval))
             {
                $checked='';
                foreach($optval as $val)
               {
                   if($val!==null && $val == $value)
                  {
                     $checked='checked="checked"';
                     break;
                  }
               }
             }
              else
             {
                $checked  = $optval !== NULL && $optval == $value ?
                'checked="checked"' : '';
             }
              
              $options[] = "<input type='checkbox' name='{$input_name}[]' value='{$value}' {$checked}><i>{$label}</i>";
           
           }  
         }                                                                                                                                                                                                                                                                                                                                                                     
         return implode("\n", $options);
    }

    private function record_group_current_count ()
    {
        $level = $this->_group_level;
        if (! isset($this->_group_count[$level]))
            $this->_group_count[$level] = 0;

        $this->_group_count[$level] += 1;
    }

    private function current_group_suffix ()
    {
        $level = $this->_group_level;
        if ($level == 1)
        {
            return '[]';
        }
        else if ($level == 2)
        {
            $level = $level - 1;
            $index = Arr::get($this->_group_count, $level, 0) - 1;
            return "[$index][]";
        }
        else 
        {
            return '_ERROR_';
        }
    }
}
